package com.yzk.frame.orm.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Service;

import com.yzk.frame.utils.util.AssertUtils;
import com.yzk.frame.utils.util.Page;

@Service
public class GenericDAO<T,PK extends Serializable>{

	private EntityManager entityManager;
	private Class<T> entity;
//	private Object[] params;
	
	public GenericDAO(){}
	
	/**
	 * 用于用于省略Dao层, 在Service层直接使用通用DAO的构造函数.
	 * 在构造函数中定义对象类型Class.
	 * eg.
	 * GenericDAO<User, Long> userDao = new GenericDAO<User, Long>(entityManager, User.class);
	 */
	public GenericDAO(EntityManager entityManager,Class<T> entity) {
		this.entityManager = entityManager;
		this.entity = entity;
	}
	
	public EntityManager getEntityManager() {
		return entityManager;
	}

//	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	
//	private static EntityManagerFactory emf;
//    private ThreadLocal<EntityManager> entityManager;
//	private EntityManager entityManager;
/*    public EntityManager getEntityManager() {
        EntityManager manager = entityManager.get();
        if (manager == null) {
            manager = emf.createEntityManager();
            entityManager.set(manager);
        }
        return manager;
    }*/
    
	public boolean save(T entity) {
		AssertUtils.notNull(entity,"对象不能为空");
		this.getEntityManager().persist(entity);
		return true;
	}

	public boolean update(T entity) {
		AssertUtils.notNull(entity,"对象不能为空");
		entityManager.merge(entity);
		return true;
	}

	public boolean delete(Serializable id) {
		AssertUtils.notNull(id,"id不能为空");
		T t = (T)this.findById(id) ;
		if(entityManager.contains(t)) {
			t = entityManager.merge(t) ;
		}
		entityManager.remove(t) ;
		return true;
	}

	public T findById(Serializable id) {
		AssertUtils.notNull(id,"id不能为空");
		return entityManager.find(entity, id);
	}

	@SuppressWarnings("unchecked")
	public T getByProperty(String propertyName, String propertyValue) {
		AssertUtils.notNull(propertyName,"参数不能为空");
		StringBuffer sb  = new StringBuffer() ;
		sb.append("from ");
		sb.append(entity.getSimpleName());
		sb.append(" where 1=1");
		if(null!=propertyName && !"".equals(propertyName)) {
			sb.append(" and ") ;
			sb.append(propertyName);
			sb.append("=?");
		}
		Query query = this.entityManager.createQuery(sb.toString()) ;
		query.setParameter(0, propertyValue) ;
		return (T)query.getSingleResult();
	}

	public List<T> query(String sql) {
		//
		return this.query(sql, null);
	}

	@SuppressWarnings("unchecked")
	public List<T> query(String sql, Object...params) {
		Query query = this.createQuery(sql, params) ;
		return query.getResultList() ;
	}

	/*
	public List<T> query(String sql, Object...params,int begin, int max) {
		Query query = this.createQuery(sql, params) ;
		return query.getResultList() ;
	}
	*/
	
	public Query createQuery(String sql ,Object...params) {
		Query query = this.entityManager.createQuery(sql) ;
		if(null!=params&&params.length>0) {
			for(int i=0;i<params.length;i++) {
				query.setParameter(i, params[i]);
			}
		}
		return query;
	}

	@SuppressWarnings("unchecked")
	public T uniqueResult(String sql, Object...params) {
		Query query = this.createQuery(sql, params) ;
		return (T)query.getSingleResult();
	}

	public Page<T> getByPage(Page<T> page,String sql ,Object...params) {
		String countHql = this.getCountHql(sql);
		Query query = this.createQuery(countHql, params);
		int totalCount = ((Long) query.getSingleResult()).intValue();
		page.setTotalItems(totalCount);
		query = this.createQuery(sql, params);

		if (page.isFirstSetted()) {
			query.setFirstResult(page.getFirst());
		}
		if (page.isPageSizeSetted()) {
			query.setMaxResults(page.getPageSize());
		}
		List result = query.list();
		if (result != null && result.size() > 0) {
			page.setResult(result);
		}
		return page;
		return page;
	}
	
	public String getCountHql(String hql) {
		int num = hql.indexOf("order by");
		if (num != -1) {
			hql = hql.substring(0, num);
		}
		int index = hql.indexOf("from");
		if (index != -1) {
			return "select count(*) " + hql.substring(index);
		}
		throw new RuntimeException("不合法的Hql语句");
	}

	
	public int execute(String sql) {
		// TODO Auto-generated method stub
		return 0;
	}

	public int execute(String sql, Collection paras) {
		// TODO Auto-generated method stub
		return 0;
	}

	public void flush() {
		this.getEntityManager().flush();
	}

	public void begin(){
		this.getEntityManager().getTransaction().begin();
	}
	
	public void commit() {
		this.getEntityManager().getTransaction().commit();
	}
	
	public void rollback() {
		this.getEntityManager().getTransaction().rollback();
	}
	
}
